package com.zsk.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
 * File opration
 * 
 * @author zincredible
 * @date 2019/04/02 13:51:39
 */

public class FileUtil {
    
	private final static DecimalFormat TWOPOINT_FORMAT = new DecimalFormat("#.00");

	/**
	 * make dir
	 * 
	 * @param dirPath
	 */
	public static void makeDir(String dirPath) {
		File file = new File(dirPath);
		if (!file.isDirectory())
			file.mkdirs();
	}

	/**
	 * Unzip file
	 * 
	 * @param zipFile zip fike
	 * @param desFile target dir
	 * @throws IOException
	 */
	public static void unZip(File zipFile, File desFile) {
		ZipFile zf = null;
		try {
			System.out.println("input zip file " + zipFile.getCanonicalPath());
			System.out.println("unzip dir " + desFile.getCanonicalPath());
			zf = new ZipFile(zipFile);
			String dirPath = desFile.getCanonicalPath();
			Enumeration<?> e = zf.entries();
			while (e.hasMoreElements()) {
				ZipEntry ze2 = (ZipEntry) e.nextElement();
				String entryName = ze2.getName();
				String path = dirPath + "/" + entryName;
				if (ze2.isDirectory()) {
					File decompressDirFile = new File(path);
					if (!decompressDirFile.exists())
						decompressDirFile.mkdirs();
				} else {
					String fileDir = path.substring(0, path.lastIndexOf("/"));
					File fileDirFile = new File(fileDir);
					if (!fileDirFile.exists())
						fileDirFile.mkdirs();

					BufferedOutputStream bos = null;
					BufferedInputStream bi = null;
					try {
						bos = new BufferedOutputStream(new FileOutputStream(dirPath + "/" + entryName));
						bi = new BufferedInputStream(zf.getInputStream(ze2));
						byte[] readContent = new byte[1024];
						int readCount = bi.read(readContent);
						while (readCount != -1) {
							bos.write(readContent, 0, readCount);
							readCount = bi.read(readContent);
						}
					} catch (Exception ex) {
						ex.printStackTrace();
					} finally {
						if (bos != null)
							bos.close();
						if (bi != null)
							bi.close();
					}
				}
			}
			System.out.println("unzip file " + zipFile.getCanonicalPath() + " success");
		} catch (ZipException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			if (zf != null)
				try {
					zf.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

	}

	public static void close(OutputStream os) {
		if (os != null) {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void close(InputStream os) {
		if (os != null) {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void deleteDir(String dir) {
		File dirFile = new File(dir);
		deleteFileOrFolder(dirFile);
	}

	/**
	 * Delete file directory
	 * 
	 * @param dir
	 */
	public static void deleteFileOrFolder(File file) {
		if (file == null || !file.exists() || !file.isDirectory())
			return;
		for (File f : file.listFiles()) {
			if (f.isFile())
				f.delete();
			else if (file.isDirectory())
				deleteFileOrFolder(f);
		}
		file.delete();
	}

	/**
	 * Clear the folder and create one if it does not exist
	 * 
	 * @param dir
	 */
	public static void emptyDir(String dir) {
		try {
			File dirFile = new File(dir);
			deleteFileOrFolder(dirFile);
			dirFile.mkdirs();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Clear the folder and create one if it does not exist
	 * 
	 * @param dir
	 */
	public static void emptyDir(File dir) {
		deleteFileOrFolder(dir);
		dir.mkdirs();
	}

	/**
	 * 精确到两位小数
	 * 
	 * @param num
	 * @return
	 */
	public static double getTwoPointNum(double num) {
		String str = TWOPOINT_FORMAT.format(num);
		double temp = Double.valueOf(str);
		return temp;
	}

	/**
	 * byte 换算成KB或MB
	 * 
	 * @param size
	 * @return
	 */
	public static String getFileSize(long size) {
		String fileSize = "";
		if (size > 1024 * 1024) {
			double lenght = size / 1024.0 / 1024.0;
			fileSize = getTwoPointNum(lenght) + "MB";
			return fileSize;
		}
		double lenght = size / 1024.0;
		fileSize = getTwoPointNum(lenght) + "KB";
		return fileSize;
	}

	/**
	 * 获取文件夹大小
	 * 
	 * @param file
	 * @return
	 */
	private static long getTotalSizeOfFilesInDir(final File file) {
		if (file.isFile())
			return file.length();
		final File[] children = file.listFiles();
		long total = 0;
		if (children != null)
			for (final File child : children)
				total += getTotalSizeOfFilesInDir(child);
		return total;
	}

	/**
	 * 获取文件夹下文件大小
	 * 
	 * @return
	 */
	public static String getDirSize(String dir) {
		String size = "";
		try {
			File file = new File(dir);
			size = getFileSize(getTotalSizeOfFilesInDir(file));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return size;
	}

	/**
	 * 深度搜索遍历文件夹
	 * 
	 * @param dirPath
	 * @param list
	 */
	public static void dfsListFile(String dirPath, List<String> list) {
		File file = new File(dirPath);
		File[] files = file.listFiles();
		for (File tmpFile : files) {
			if (tmpFile.isDirectory()) {
				dfsListFile(tmpFile.getAbsolutePath(), list);
			} else {
				list.add(tmpFile.getAbsolutePath());
			}
		}
	}

	/**
	 * 广度搜索遍历文件夹
	 * 
	 * @param dirPath
	 * @param list
	 */
	public static void bfsListFile(String dirPath, List<String> list) {
		File file = new File(dirPath);
		File[] fs = file.listFiles();
		Queue<File> queue = new LinkedList<>();

		// 遍历第一层
		for (File f : fs) {
			// 把第一层文件夹加入队列
			if (f.isDirectory())
				queue.offer(f);
			else
				list.add(f.getAbsolutePath());
		}
		// 逐层搜索下去
		while (!queue.isEmpty()) {
			// 从队列头取一个元素
			File fileTemp = queue.poll();
			File[] fileListTemp = fileTemp.listFiles();
			for (File f : fileListTemp) {
				if (f.isDirectory())
					queue.offer(f);
				else
					list.add(f.getAbsolutePath());
			}
		}

	}

	public static void main(String[] args) {
//		System.out.println("广度搜索");
//		List<String> list = new ArrayList<>();
//		bfsListFile("E:\\spring-cloud-example\\server-consumer", list);
//		for (String string : list) {
//			System.out.println(string);
//		}
//		System.out.println("深度搜索");
//		list.clear();
//		dfsListFile("E:\\spring-cloud-example\\server-consumer", list);
//		for (String string : list) {
//			System.out.println(string);
//		}

		unZip(new File("D:\\360安全浏览器下载\\weui-master.zip"), new File("E:\\zsk"));

	}
}
